<template>
  <div class="app">
    <el-tabs v-model="activeTabs" class="demo-tabs">
      <el-tab-pane label="知识库爬取" name="repository">
        <!-- 知识库爬取内容 -->
        <el-container class="content">
          <el-header height="10">
            <h2>语雀知识库下载</h2>
          </el-header>
          <el-main class="main">
            <el-input
                placeholder="知识库链接"
                v-model="repoUrl"
                :suffix-icon="repoUrlIcon"
                class="input-url"
                :clearable="repoUrlIcon === ''"
            />
            <el-tooltip content="爬取开始后请不要刷新页面">
              <el-button
                  :disabled="!repoCanSubmit"
                  type="primary"
                  @click="startRepoMission"
              >提交爬取任务</el-button>
            </el-tooltip>
          </el-main>
          <el-footer class="footer" height="200" v-if="repoEnableList">
            <div>
              <el-progress
                  :text-inside="true"
                  :stroke-width="20"
                  :status="repoProgressStatus"
                  :percentage="repoProgress"
              >
                <span>{{ repoProgress }}% {{ repoProgressLabel }}</span>
              </el-progress>
            </div>
            <el-collapse v-model="repoActiveDocList" class="collapse">
              <el-collapse-item title="已爬取文档树列表" name="1">
                <div class="doc-tree">
                  <el-tree
                      :data="repoTreeData"
                      :props="{ children: 'children', label: 'title' }"
                      default-expand-all
                      node-key="uuid"
                  >
                    <template #default="{ node, data }">
                      <span class="custom-tree-node" :style="{ color: data.status ? 'inherit' : 'red' }">
                        <span>{{ node.label }}</span>
                        <span v-if="data.type === 'DOC'">
                          <span v-if="data.status">
                            <a v-if="data.status" @click="toLink(data.url)"> 查看来源 </a>
                            <a v-if="data.status" style="margin-left: 8px" @click="downloadRepoDoc(data.title)"> 下载Markdown </a>
                          </span>
                          <span v-else> 爬取失败</span>
                        </span>
                      </span>
                    </template>
                  </el-tree>
                </div>
              </el-collapse-item>
            </el-collapse>
            <div>
              <el-tooltip content="爬取完成后有1分钟时间进行下载">
                <el-button
                    style="margin-top: 10px"
                    :disabled="repoProgress !== 100"
                    type="primary"
                    @click="downloadRepoDocs"
                >一键下载Markdown</el-button>
              </el-tooltip>
            </div>
          </el-footer>
        </el-container>
      </el-tab-pane>
      <el-tab-pane label="单文档爬取" name="document">
        <!-- 单文档爬取内容 -->
        <el-container class="content">
          <el-header height="10">
            <h2>语雀单文档下载</h2>
          </el-header>
          <el-main class="main">
            <el-input
                placeholder="知识库链接"
                v-model="docUrl"
                :suffix-icon="docUrlIcon"
                class="input-url"
                :clearable="docUrlIcon === ''"
            />
            <span>
              <el-tooltip content="爬取开始后请不要刷新页面">
                <el-button
                    :disabled="!docCanSubmit"
                    type="primary"
                    @click="startDocMission"
                >下载Markdown</el-button>
              </el-tooltip>
            </span>
          </el-main>
        </el-container>
      </el-tab-pane>
    </el-tabs>
  </div>
</template>

<script setup>
import { ref, computed, watch } from 'vue'
import { ElMessage } from 'element-plus'
import * as mutipleDocApi from '../api/mutiple-doc'
import * as singleDocApi from '../api/single-doc'
import * as yuqueApi from '../api/yuque-api'
import { TaskStatus } from '../constant'

// tab
const activeTabs = ref('repository')

// -------------------- 知识库爬取相关 --------------------
const repoUrl = ref('')
const repoUrlPattern = /^https?:\/\/www\.yuque\.com\/[^/]+\/[^/]+/
const repoUrlIcon = computed(() => {
  if (!repoUrl.value) return ''
  return repoUrlPattern.test(repoUrl.value) ? 'CircleCheckFilled' : ''
})
const repoCanSubmit = ref(false)
watch(repoUrl, val => {
  repoCanSubmit.value = repoUrlPattern.test(val)
})
const repoEnableList = ref(false)
const repoDocTree = ref([])
const repoTreeData = ref([])
const repoProgress = ref(0)
const repoProgressStatus = ref('')
const repoProgressLabel = ref('下载中')
const repoActiveDocList = ref(['1'])
const repoTaskId = ref('')
const resetTimeout = 60000

function startRepoMission() {
  mutipleDocApi.startMultipleTask(repoUrl.value).then(res => {
    ElMessage.success('任务提交成功')
    const data = res.data
    repoTaskId.value = data.data.taskId
    getRepoMissionStatus()
    repoProgress.value = 0
    repoProgressStatus.value = ''
    repoProgressLabel.value = '正在开始'
    repoEnableList.value = true
  }).catch(err => {
    console.error(err)
    repoCanSubmit.value = true
    ElMessage.error(err.response.data.message)
  })
}

function getRepoMissionStatus() {
  const intervalId = setInterval(() => {
    yuqueApi.getTaskStatus(repoTaskId.value).then(res => {
      const data = res.data.data
      repoDocTree.value = data.docTree
      repoTreeData.value = buildTree(data.docTree)
      repoProgress.value = data.progress
      if (data.status === TaskStatus.SUCCESS) {
        clearInterval(intervalId)
        repoProgressStatus.value = 'success'
        repoProgressLabel.value = '爬取完成'
        repoCanSubmit.value = true
        ElMessage.success('爬取完成')
        setTimeout(resetRepoState, resetTimeout)
      } else if (data.status === TaskStatus.WARNING_SUCCESS) {
        clearInterval(intervalId)
        repoProgressStatus.value = 'warning'
        repoProgressLabel.value = '爬取完成'
        repoCanSubmit.value = true
        ElMessage.warning('爬取完成，丢失文档数量：' + data['lostMissions'])
        setTimeout(resetRepoState, resetTimeout)
      } else if (data.status === TaskStatus.WARNING) {
        repoProgressStatus.value = 'warning'
        repoProgressLabel.value = '存在无法访问的私有文档'
      } else if (data.status === TaskStatus.FAILURE) {
        clearInterval(intervalId)
        repoProgressStatus.value = 'exception'
        repoProgressLabel.value = '爬取失败'
        repoCanSubmit.value = true
        ElMessage.error('爬取失败')
      } else if (data.status === TaskStatus.RUNNING) {
        repoProgressStatus.value = ''
        repoCanSubmit.value = false
        repoProgressLabel.value = '下载中'
      }
    }).catch(err => {
      clearInterval(intervalId)
      console.error(err)
      repoProgressStatus.value = 'exception'
      repoProgressLabel.value = '任务失败'
      repoCanSubmit.value = true
      ElMessage.error(err.response.data.message)
    })
  }, 500)
}

function resetRepoState() {
  repoUrl.value = ''
  repoEnableList.value = false
  repoCanSubmit.value = true
  repoDocTree.value = []
  repoTreeData.value = []
  repoProgress.value = 0
  repoProgressStatus.value = ''
  repoProgressLabel.value = '下载中'
  repoActiveDocList.value = ['1']
  repoTaskId.value = ''
}

function downloadRepoDocs() {
  mutipleDocApi.downloadDocs(repoTaskId.value)
}
function downloadRepoDoc(title) {
  mutipleDocApi.downloadDoc(repoTaskId.value, title)
}
function buildTree(data) {
  const tree = []
  const map = {}
  data.forEach(item => {
    map[item.uuid] = { ...item, children: [] }
  })
  data.forEach(item => {
    if (item.parentId && map[item.parentId]) {
      map[item['parentId']].children.push(map[item.uuid])
    } else {
      tree.push(map[item.uuid])
    }
  })
  return tree
}
function toLink(url) {
  window.open(url)
}

// -------------------- 单文档爬取相关 --------------------
const docUrl = ref('')
const docUrlPattern = /^https?:\/\/www\.yuque\.com\/[^/]+\/[^/]+/
const docUrlIcon = computed(() => {
  if (!docUrl.value) return ''
  return docUrlPattern.test(docUrl.value) ? 'CircleCheckFilled' : ''
})
const docCanSubmit = ref(false)
watch(docUrl, val => {
  docCanSubmit.value = docUrlPattern.test(val)
})
const docTaskId = ref('')
const docTitle = ref('')

function startDocMission() {
  singleDocApi.startOneTask(docUrl.value).then(res => {
    ElMessage.success('任务提交成功')
    const data = res.data
    docTaskId.value = data.data.taskId
    getDocMissionStatus()
    docCanSubmit.value = false
  }).catch(err => {
    console.error(err)
    docCanSubmit.value = true
    ElMessage.error(err.response.data.message)
  })
}
function downloadDoc() {
  singleDocApi.getDownloadOneTaskUrl(docTaskId.value)
}
function getDocMissionStatus() {
  const intervalId = setInterval(() => {
    yuqueApi.getTaskStatus(docTaskId.value).then(res => {
      const data = res.data.data
      if (data.status === 'SUCCESS') {
        clearInterval(intervalId)
        docCanSubmit.value = true
        docTitle.value = data.docTitle
        ElMessage.success('爬取完成')
        downloadDoc()
      } else if (data.status === 'FAILURE') {
        clearInterval(intervalId)
        docCanSubmit.value = true
        ElMessage.error('爬取失败')
      }
    }).catch(err => {
      clearInterval(intervalId)
      console.error(err)
      docCanSubmit.value = false
      ElMessage.error(err.response.data.message)
    })
  }, 500)
}
</script>

<style scoped>
.app {
  box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 20px;
}
.input-url {
  width: 300px;
  margin-right: 10px;
}
.doc-tree {
  height: 200px;
  width: 100%;
  max-height: 200px;
  display: flex;
  overflow-y: auto;
  justify-content: center;
}
.main {
  flex-direction: row;
  flex-wrap: nowrap;
  justify-content: space-between;
}
a {
  font-size: 12px;
  margin-left: 10px;
}
</style>